#include <func.h>
#include <mysql/mysql.h>

int GETS_handle(const char* username, int netfd, const char* path, const char* filename){

    //拼接前置路径和文件名
    char allPath[1024];
    strcpy(allPath,path);
    if(allPath[strlen(allPath)-1] != '/'){
        strcat(allPath,"/");
    }
    strcat(allPath,filename);

    //查询数据库，判断目标文件是否存在
    MYSQL * mysql = mysql_init(NULL); // 为mysql连接分配内存（线程不安全）
    MYSQL * ret = mysql_real_connect(mysql,"localhost","root","2891","netdisk",0,NULL,0);//密码和库名需要根据情况更改
    if(ret == NULL){
        fprintf(stderr,"mysql connect error:%s\n", mysql_error(mysql));
        return -1;
    }
    char sql[1024] = {0};
    sprintf(sql,"select * from fileInfo where name=%s and user=%s and type=f and tomb=0;"
            ,filename,username);
    int qret = mysql_query(mysql,sql);
    if(qret != 0){
        fprintf(stderr,"sql error:%s\n", mysql_error(mysql));
        return -1;
    }
    MYSQL_RES *result = mysql_store_result(mysql); //取出读取的结果
    printf("total rows = %lu\n", mysql_num_rows(result));
    //查找路径匹配的那一项（递归）
    MYSQL_ROW row;
    char path_sql[1024];
    bool is_pathRigtt = 0;
    char md5[32+1];
    while((row = mysql_fetch_row(result)) != NULL){
        memset(path_sql,0,sizeof(path_sql));
        strcat(path_sql,filename);

        MYSQL_ROW row_preid;
        char sql_preid[1024] = {0};
        sprintf(sql_preid,"select * from fileInfo where id = %s;",row[3]);
        qret = mysql_query(mysql,sql_preid);
        if(qret != 0){
            fprintf(stderr,"sql error:%s\n", mysql_error(mysql));
            return -1;
        }
        MYSQL_RES *result_preid = mysql_store_result(mysql); //取出读取的结果
        row_preid = mysql_fetch_row(result_preid);
        char tmp[1024];
        strcpy(tmp,path_sql);
        sprintf(path_sql,"%s/%s",row_preid[1],tmp);
        do{
            memset(sql_preid,0,sizeof(sql_preid));
            sprintf(sql_preid,"select * from fileInfo where id = %s;",row_preid[3]);
            qret = mysql_query(mysql,sql_preid);
            if(qret != 0){
                fprintf(stderr,"sql error:%s\n", mysql_error(mysql));
                return -1;
            }
            MYSQL_RES *result_preid = mysql_store_result(mysql); //取出读取的结果
            row_preid = mysql_fetch_row(result_preid);
            strcpy(tmp,path_sql);
            sprintf(path_sql,"%s/%s",row_preid[1],tmp);

        }
        while(strcmp(row_preid[3],"-1"));
        if(strcmp(path_sql,allPath) == 0){
            is_pathRigtt = 1;
            strcpy(md5,row[5]);
        }
    }

    train_t train;//创建小火车
    memset(&train,0,sizeof(train));

    //如果不存在，通知客户端，退出
    if(!is_pathRigtt){
        //TO DO 错误处理
        printf("no file!");
        train.length = -1;
        memcpy(train.data,"ERROR:NO FILE!",14);
        send(netfd,&train,sizeof(train_t),MSG_NOSIGNAL);
        SYSLOG(username,"GETS",path,"FAIL:NO FILE!");
        return -1;
    }
    //如果存在，通知客户端，继续
    train.length = 0;
    memcpy(train.data,"ALLOW GETS!",11);
    send(netfd,&train,sizeof(train_t),MSG_NOSIGNAL);

    //接收已存在文件的大小
    off_t oldsize = 0;//传输前已存在的文件大小
    int length = 0;
    ssize_t sret = recv(netfd, &length, sizeof(length), 0); 
    sret = recv(netfd, &oldsize, length, 0);

    //（真实文件名）打开文件
    int fd = open(md5, O_RDWR);
    if(fd = -1){
        printf("open failed in GETS_handle!");
        return -1;
    }

    struct stat statbuf;
    fstat(fd,&statbuf);
    train.length = sizeof(statbuf.st_size);
    memcpy(train.data,&statbuf.st_size,train.length);
    send(netfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);// 发文件的大小

    //如果文件大小小于100M，直接发送
    if(statbuf.st_size < 100*1024*1024){
        lseek(fd,oldsize,SEEK_SET);
        while(1){
            bzero(&train,sizeof(train));
            ssize_t sret = read(fd,train.data,sizeof(train.data)); 
            train.length = sret;
            //即使文件已经读完了，也发一个空车厢火车过去
            //目标是让客户端知道文件已经发完了
            send(netfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);// 发文件的内容
            if(sret == 0){
                break;
            }
        }
    }
    //如果文件大小大于100M，使用mmap然后发送
    else{
        off_t totalsize = oldsize;//已传输的文件大小
        char *p = (char *)mmap(NULL,statbuf.st_size,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);
        ERROR_CHECK(p,MAP_FAILED,"mmap");
        while(totalsize < statbuf.st_size){
            if(statbuf.st_size - totalsize > 1000){
                train.length = 1000;//剩余未发送的内容超过1000
            }
            else{
                train.length = statbuf.st_size - totalsize;
                //剩余内容不足1000
            }
            send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);//发火车头
            send(netfd,p+totalsize,train.length,MSG_NOSIGNAL);//火车车厢在mmap映射区
            totalsize += train.length;
        }
        // 补发一个空火车
        train.length = 0;
        send(netfd,&train.length,sizeof(train.length),MSG_NOSIGNAL);//发火车头
        munmap(p,statbuf.st_size);
    }

    //发送MD5码
    train.length = sizeof(md5);
    memcpy(train.data,md5,sizeof(md5));
    send(netfd,&train,sizeof(int)+train.length,MSG_NOSIGNAL);

    close(fd);
    SYSLOG(username,"GETS",path,"success");

    mysql_free_result(result);
    mysql_close(mysql);


    return 0;
}

